/**
 * 20220118：由原virtualPlane分离
 */
import {Euler, Matrix4, Mesh, Triangle, Vector2, Vector3} from "three";
import VirtualPlaneGeometry from "../geometry/virtual-plane-geometry";
import VirtualPlaneMaterial from "../materials/virtual-plane-material";

const _alignedPosition = new Vector2();
const _rotatedPosition = new Vector2();
const _viewWorldMatrix = new Matrix4();
const _vA = new Vector3();
const _vB = new Vector3();
const _vC = new Vector3();
const _uvA = new Vector2();
const _uvB = new Vector2();
const _uvC = new Vector2();
const _vD = new Vector3();
const _intersectPoint = new Vector3();
const _worldScale = new Vector3();
const _mvPosition = new Vector3();
const _mA=new Matrix4();
const _eA=new Euler();

/**
 * 虚拟平面（类sprite）
 */
export default class VirtualPlane extends Mesh{
    constructor(geometry=new VirtualPlaneGeometry(),material=new VirtualPlaneMaterial()){
        super(geometry,material);
        this.type='MeshPoint';
    }

    /**
     * 射线检测函数
     * @param raycaster
     * @param intersects
     */
    raycast( raycaster, intersects ) {
        if ( raycaster.camera === null ) {
            console.error( 'MeshPoint: "Raycaster.camera" needs to be set in order to raycast against.' );
        }
        _worldScale.setFromMatrixScale( this.matrixWorld );
        _viewWorldMatrix.copy( raycaster.camera.matrixWorld );
        this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
        _mvPosition.setFromMatrixPosition( this.modelViewMatrix );
        if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
            _worldScale.multiplyScalar( - _mvPosition.z );
        }
        _mA.extractRotation(this.matrixWorld);
        _eA.setFromRotationMatrix(_mA,'XYZ');
        const rotation = _eA.z;
        let sin, cos;
        if ( rotation !== 0 ) {
            cos = Math.cos( rotation );
            sin = Math.sin( rotation );
        }
        const center = _vD.set(this.material.center.x,this.material.center.y,0);
        VirtualPlane.transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
        VirtualPlane.transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
        VirtualPlane.transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
        _uvA.set( 0, 0 );
        _uvB.set( 1, 0 );
        _uvC.set( 1, 1 );
        let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint );
        if ( intersect === null ) {
            VirtualPlane.transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
            _uvB.set( 0, 1 );
            intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint );
            if ( intersect === null ) {
                return;
            }
        }
        const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
        if ( distance < raycaster.near || distance > raycaster.far ) return;
        intersects.push( {
            distance: distance,
            point: _intersectPoint.clone(),
            uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ),
            face: null,
            object: this
        } );
    }

    static transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
        _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
        if ( sin !== undefined ) {
            _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
            _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
        } else {
            _rotatedPosition.copy( _alignedPosition );
        }
        vertexPosition.copy( mvPosition );
        vertexPosition.x += _rotatedPosition.x;
        vertexPosition.y += _rotatedPosition.y;
        vertexPosition.applyMatrix4( _viewWorldMatrix );
    }
}